
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Threading;
using Swaf.Container;

namespace Swaf
{
	internal class ExpirationManager
	{
		protected int m_checkInterval;
		protected IList m_expireItems;
		protected Thread m_workThread;

		public ExpirationManager()
		{
			m_checkInterval = 1000;
			m_expireItems = new ArrayList();
			m_workThread = new Thread(new ThreadStart(workThread));
			m_workThread.Name="ExpirationManager";
#if(!COMPACT_FRAMEWORK)
			m_workThread.IsBackground = true;
#endif
			//Register a new app shutdown handler to make sure all expiration nodes are disposed of appropriately.
			((IAppManagement)Application.globalApp).OnAppShutdown += new AppShutdownRequest(expireAll);
			m_workThread.Start();
		}
		public void expireAll(IApplication app)
		{
			expireAll();
		}
		public void expireAll()
		{
			lock(m_expireItems) 
			{
				ArrayList itemsToRemove = new ArrayList();

				foreach(WeakReference node in m_expireItems) 
				{
					if(node.IsAlive)
					{
						((IExpireNode)node.Target).clear();

						// Set item to be removed from the collection
						itemsToRemove.Add(node);
					}
				}

				// Remove items that need to be removed.
				foreach (WeakReference node in itemsToRemove)
				{
					m_expireItems.Remove(node);
				}
			}
		}
		public void addItem(IExpireNode item)
		{
			lock(m_expireItems)
			{
				WeakReference w = new WeakReference(item);
				if(item != null && !m_expireItems.Contains(w))
					m_expireItems.Add(w);
			}
		}

		protected void workThread()
		{
			try 
			{
				while(true) 
				{
					checkExpirations();
					Thread.Sleep(m_checkInterval);
				}
			}
			catch(Exception e) 
			{
			}
		}

		protected void checkExpirations()
		{
			lock(m_expireItems) 
			{
				ArrayList itemsToRemove = new ArrayList();

				foreach(WeakReference node in m_expireItems) 
				{
					if(node.IsAlive)
					{
						((IExpireNode)node.Target).check();
						if (((IExpireNode)node.Target).isExpired)
						{
							itemsToRemove.Add(node);
						}
					}
					else 
					{
						itemsToRemove.Add(node);
					}
				}

				// Remove items that need to be removed.
				foreach (WeakReference node in itemsToRemove)
				{
					m_expireItems.Remove(node);
				}
			}
		}
	}

}
